﻿module Utils

open System
open System.Collections.Generic
open System.Linq
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Audio
open Microsoft.Xna.Framework.Content
open Microsoft.Xna.Framework.GamerServices
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input
open Microsoft.Xna.Framework.Media
open Utilities
                 
let zoom_enemie_rage = 1.8f

let rec take lst n =  
  match lst,n with
    _ , 0    -> []
   |(x::xs),n-> x::(take xs (n-1))
   |_ -> lst
let rec drop lst n =
  match lst,n with
    _ , 0    -> lst
   |(x::xs),n-> drop xs (n-1)
   |_ -> lst

type Microsoft.Xna.Framework.Game with
  member this.AddService<'a> (s:'a) =
    this.Services.AddService(typeof<'a>, s)
  member this.GetService<'a>() = 
    this.Services.GetService(typeof<'a>) :?> 'a
  member this.RemoveService<'a>() =
    this.Services.RemoveService(typeof<'a>)

type Random with
  member this.NextFloat with get() = this.NextDouble() |> float32

type MouseState with
  member this.Position with get() = Vector2(this.X |> float32, this.Y |> float32)

type Texture2D with
  member this.Size with get() = Vector2(this.Width |> float32, this.Height |> float32)

type GraphicsDevice with
  member this.Width with get() = this.Viewport.Width |> float32
  member this.Height with get() = this.Viewport.Height |> float32
  member this.ScreenSize with get() = Vector2(this.Width,this.Height)

let over (r:Rectangle) (p:Vector2) = r.Contains(p.X |> int, p.Y |> int)

type ISmoothStep<'a> =
  abstract member smooth_with : 'a -> float32 -> 'a

type Animation<'a when 'a :> ISmoothStep<'a>> = { Start:'a; End:'a; StartTime:float32; Velocity:float32 } with
  member this.Curr T = this.Start.smooth_with this.End (this.Velocity * (T - this.StartTime))
  member this.Finished T = (this.Velocity * (T - this.StartTime)) >= 1.0f

type Position = { X : float32; Y : float32 } with
  interface ISmoothStep<Position> with
    member this.smooth_with other a =
      { X = MathHelper.SmoothStep(this.X, other.X, a); Y = MathHelper.SmoothStep(this.Y, other.Y, a) }
  member this.ToVector2 with get() = Vector2(this.X, this.Y)

type Vector2 with
  member this.ToPosition with get() = { X = this.X; Y = this.Y }

//type Utilities.ArrayList<'a> with
//  member this.find_index (f : Func<'a->bool>) =
//      let ln = this.Length
//      let value = ref -1
//      for i in seq {0..ln} do
//        if (f.Invoke() (this.ElementAt(i))) then 
//          value := i
//      !value
let find_index (lst:ArrayList<'a>) (f : 'a->bool) =
    let ln = lst.Count
    let value = ref []
    for i in seq {0..ln - 1} do
      if f (lst.[i]) then 
        value := i :: !value
    !value
type Timer = { Value : float32 } with
  interface ISmoothStep<Timer> with
    member this.smooth_with other a = { Value = MathHelper.SmoothStep(this.Value, other.Value, a) }
  member this.ToFloat with get() = this.Value
  
type System.Single with
  member this.ToTimer with get() = { Value = this }

type RGB = {R : byte; G : byte; B : byte} with
  member this.ToColor with get() = Color(int this.R, int this.G, int this.B)

type Color with
  member this.ToRGB with get() = { R = this.R; G = this.G; B = this.B }

type System.TimeSpan with
  member this.DT with get() = this.TotalSeconds |> float32
